﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace IISLogAnalyzer
{
    public static class ControlProxyHelper
    {
        /// <summary>
        /// 查找控件
        /// </summary>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="name">控件名称</param>
        /// <returns></returns>
        public static Control FindControlByName(Control parent, string name)
        {
            foreach (Control control in parent.Controls)
            {
                if (control.Name == name)
                {
                    return control;
                }

                // 如果控件内部还有子控件，递归查找  
                var foundControl = FindControlByName(control, name);
                if (foundControl != null)
                {
                    return foundControl;
                }
            }
            return null;
        }

        /// <summary>
        /// 调用控件事件
        /// </summary>
        /// <typeparam name="TEventArgs">控件事件</typeparam>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="controlName">控件名称</param>
        /// <param name="eventName">控件方法名称</param>
        /// <param name="eventHandler">实现控件事件</param>
        public static void SubscribeToEvent<TEventArgs>(Control parent, string controlName, string eventName, EventHandler<TEventArgs> eventHandler)
        {
            var control = FindControlByName(parent, controlName);
            if (control == null)
            {
                throw new ArgumentException($"Control with name {controlName} not found.");
            }

            var eventInfo = control.GetType().GetEvent(eventName);
            if (eventInfo == null)
            {
                throw new ArgumentException($"Event {eventName} not found on control.");
            }

            eventInfo.AddEventHandler(control, Delegate.CreateDelegate(eventInfo.EventHandlerType, eventHandler.Method));
        }

        /// <summary>
        /// 为控件赋值
        /// </summary>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="controlName">控件名称</param>
        /// <param name="propertyName">控件属性</param>
        /// <param name="value">控件属性值</param>
        public static void SetProperty(Control parent, string controlName, string propertyName, object value)
        {
            var control = FindControlByName(parent, controlName);
            if (control == null)
            {
                throw new ArgumentException($"Control with name {controlName} not found.");
            }

            var propertyInfo = control.GetType().GetProperty(propertyName);
            if (propertyInfo == null)
            {
                throw new ArgumentException($"Property {propertyName} not found on control.");
            }

            if (propertyInfo.CanWrite)
            {
                propertyInfo.SetValue(control, value);
            }
            else
            {
                throw new InvalidOperationException($"Property {propertyName} is not writable.");
            }
        }

        /// <summary>
        /// 调用控件本身的方法
        /// </summary>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="controlName">控件名称</param>
        /// <param name="methodName">控件方法名称</param>
        /// <param name="parameters">方法参数</param>
        public static void InvokeControlMethod(Control parent, string controlName, string methodName, params object[] parameters)
        {
            Control control = FindControlByName(parent, controlName);
            if (control == null)
            {
                throw new ArgumentException($"Control with name {controlName} not found.");
            }

            MethodInfo methodInfo = control.GetType().GetMethod(methodName);
            if (methodInfo == null)
            {
                throw new ArgumentException($"Method {methodName} not found on control.");
            }

            methodInfo.Invoke(control, parameters);
        }


        /// <summary>
        /// 调用控件本身的方法
        /// </summary>        
        /// <param name="control">控件</param>
        /// <param name="methodName">控件方法名称</param>
        /// <param name="parameters">方法参数</param>
        public static void InvokeControlMethod(Control control, string methodName, params object[] parameters)
        {
            if (control == null)
            {
                throw new ArgumentException($"Control not found.");
            }

            MethodInfo methodInfo = control.GetType().GetMethod(methodName);
            if (methodInfo == null)
            {
                throw new ArgumentException($"Method {methodName} not found on control.");
            }

            methodInfo.Invoke(control, parameters);
        }

        /// <summary>
        /// 调用控件属性的方法
        /// </summary>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="controlName">控件名称</param>
        /// <param name="propertyName">控件属性</param>
        /// <param name="methodName">控件方法名称</param>
        /// <param name="parameters">方法参数</param>
        public static void InvokeControlMethod(Control parent, string controlName, string propertyName, string methodName, params object[] parameters)
        {
            Control control = FindControlByName(parent, controlName);
            if (control == null)
            {
                throw new ArgumentException($"Control with name {controlName} not found.");
            }

            PropertyInfo propertyInfo = control.GetType().GetProperty(propertyName);
            if (propertyInfo == null)
            {
                throw new ArgumentException($"Property {propertyName} not found on control.");
            }

            object propertyValue = propertyInfo.GetValue(control);
            if (propertyValue == null)
            {
                throw new InvalidOperationException($"Property {propertyName} returned null.");
            }

            MethodInfo methodInfo = propertyValue.GetType().GetMethod(methodName);
            if (methodInfo == null)
            {
                throw new ArgumentException($"Method {methodName} not found on property {propertyName}.");
            }

            methodInfo.Invoke(propertyValue, parameters);
        }


        /// <summary>
        /// 获取控件的 PropertyInfo  
        /// </summary>
        /// <param name="control"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static PropertyInfo GetPropertyInfo(Control control, string propertyName)
        {
            if (control == null || string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentNullException("Invalid argument.");
            }

            PropertyInfo pi = control.GetType().GetProperty(propertyName);

            if (pi == null)
            {
                throw new InvalidOperationException(
                    string.Format(
                        "Can't find property {0} in {1}.",
                        propertyName,
                        control.GetType().ToString()
                    )
                );
            }

            return pi;
        }

        /// <summary>
        /// 设置控件属性的属性的值
        /// </summary>
        /// <param name="parent">控件所在父窗体</param>
        /// <param name="controlName">控件名称</param>
        /// <param name="propertyName">控件属性</param>
        /// <param name="childName">控件属性的属性</param>
        /// <param name="parameters">方法参数</param>
        public static void InvokeControlProperty(Control parent, string controlName, string propertyName, string childName, params object[] parameters)
        {
            Control control = FindControlByName(parent, controlName);
            if (control == null)
            {
                throw new ArgumentException($"Control with name {controlName} not found.");
            }

            PropertyInfo propertyInfo = control.GetType().GetProperty(propertyName);
            if (propertyInfo == null)
            {
                throw new ArgumentException($"Property {propertyName} not found on control.");
            }

            object propertyValue = propertyInfo.GetValue(control);
            if (propertyValue == null)
            {
                throw new InvalidOperationException($"Property {propertyName} returned null.");
            }

            PropertyInfo pi = control.GetType().GetProperty(childName);
            if (pi == null)
            {
                throw new ArgumentException($"Method {childName} not found on property {propertyName}.");
            }

            if (pi.CanWrite)
            {
                pi.SetValue(control, parameters);
            }
            else
            {
                throw new InvalidOperationException($"Property {propertyName} is not writable.");
            }
        }


        /// <summary>
        /// 获取控件属性值 
        /// </summary>
        /// <param name="control">控件</param>
        /// <param name="propertyName">属性</param>        
        public static object GetValue(Control control, string propertyName)
        {
            if (control.InvokeRequired)
            {
                return control.Invoke(new MethodInvoker(() => GetValue(control, propertyName)));
            }

            PropertyInfo pi = GetPropertyInfo(control, propertyName);

            if (pi != null && pi.CanRead)
            {
                return pi.GetValue(control, null);
            }
            else
            {
                throw new FieldAccessException(
                    string.Format(
                        "{0}.{1} is a write-only property or does not exist.",
                        control.GetType().ToString(),
                        propertyName
                    )
                );
            }
        }


        /// <summary>
        /// 设置控件属性值 
        /// </summary>
        /// <param name="control">控件</param>
        /// <param name="propertyName">属性</param>
        /// <param name="value">值</param>
        public static void SetValue(Control control, string propertyName, object value)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(new MethodInvoker(() => SetValue(control, propertyName, value)));
                return;
            }

            PropertyInfo pi = GetPropertyInfo(control, propertyName);

            if (pi != null && pi.CanWrite)
            {
                pi.SetValue(control, value, null);
            }
            else
            {
                throw new FieldAccessException(
                    string.Format(
                        "{0}.{1} is a read-only property or does not exist.",
                        control.GetType().ToString(),
                        propertyName
                    )
                );
            }
        }

        /// <summary>
        /// 设置SetStatusStrip中的ToolStripStatusLabel的Text值
        /// </summary>
        /// <param name="statusStrip">statusStrip</param>
        /// <param name="itemIndex">statusStrip中的Items的index</param>
        /// <param name="text">Text值</param>
        public static void SetStatusStripText(StatusStrip statusStrip, int itemIndex, string text)
        {
            if (statusStrip.InvokeRequired)
            {
                statusStrip.Invoke(new MethodInvoker(delegate
                {
                    if (statusStrip.Items.Count > itemIndex && statusStrip.Items[itemIndex] is ToolStripStatusLabel)
                    {
                        ((ToolStripStatusLabel)statusStrip.Items[itemIndex]).Text = text;
                    }
                }));
            }
            else
            {
                if (statusStrip.Items.Count > itemIndex && statusStrip.Items[itemIndex] is ToolStripStatusLabel)
                {
                    ((ToolStripStatusLabel)statusStrip.Items[itemIndex]).Text = text;
                }
            }
        }

    }
}
